package org.jsola.hr.service.impl;

import io.swagger.annotations.ApiModelProperty;
import org.jsola.admin.entity.SiteDO;
import org.jsola.core.Page;
import org.jsola.core.entity.BaseDO;
import org.jsola.core.vo.BaseTreeVO;
import org.jsola.exception.ParamException;
import org.jsola.hr.common.ExampleKit;
import org.jsola.hr.constant.HrConstants;
import org.jsola.hr.dao.IInstitutionTypeDAO;
import org.jsola.hr.dto.InstitutionTypeAddDTO;
import org.jsola.hr.dto.InstitutionTypeUpdateDTO;
import org.jsola.hr.entity.InstitutionDO;
import org.jsola.hr.entity.InstitutionTypeDO;
import org.jsola.hr.provider.IAdminProviderService;
import org.jsola.hr.query.InstitutionTypeQuery;
import org.jsola.hr.service.IInstitutionService;
import org.jsola.hr.service.IInstitutionTypeService;
import org.jsola.hr.vo.InstitutionStatisticalVO;
import org.jsola.hr.vo.InstitutionTypeListVO;
import org.jsola.hr.vo.InstitutionTypeVO;
import org.jsola.hr.vo.InstitutionVO;
import org.jsola.user.core.TokenUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import tk.mybatis.mapper.entity.Example;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 制度分类
 *
 * @author zhr
 */
@Service("hrInstitutionTypeServiceImpl")
public class InstitutionTypeServiceImpl implements IInstitutionTypeService {

    @Autowired
    private IInstitutionTypeDAO institutionTypeDAO;

    @Autowired
    private IInstitutionService institutionService;

    @Autowired
    private IAdminProviderService adminProviderService;

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public InstitutionTypeVO save(InstitutionTypeAddDTO institutionTypeAddDTO, TokenUser tokenUser) {
        ParamException.notNull(institutionTypeAddDTO.getLevel(), "分类等级不能为空");
        if (institutionTypeAddDTO.getLevel() == 1) {
            // 一级分类 将父类Id置成0
            institutionTypeAddDTO.setParentId("0");
        } else if (institutionTypeAddDTO.getLevel() == 2) {
            // 二级分类 校验上级分类的正确性
            ParamException.notNull(institutionTypeAddDTO.getParentId(), "二级分类的上级分类不能为空");
            InstitutionTypeDO institutionTypeDO = selectDOById(institutionTypeAddDTO.getParentId(), tokenUser.getSiteId());
            ParamException.notNull(institutionTypeDO, "上级分类不存在，请刷新后重试");
        } else {
            throw new ParamException("分类等级有误");
        }

        // 转DO
        InstitutionTypeDO institutionTypeDO = institutionTypeAddDTO.to(InstitutionTypeDO.class);
        // 查询同名制度分类
        List<InstitutionTypeDO> institutionTypeDOList = selectByName(institutionTypeDO
                .getInstitutionTypeName(), tokenUser.getSiteId());
        ParamException.isTrue(CollectionUtils.isEmpty(institutionTypeDOList), "该名称已存在，无法创建");
        // 保存
        institutionTypeDO = save(institutionTypeDO, tokenUser.getSiteId(), tokenUser.getUserId());
        return institutionTypeDO.to(InstitutionTypeVO.class);
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public int update(InstitutionTypeUpdateDTO institutionTypeUpdateDTO, TokenUser tokenUser) {
        //转DO
        InstitutionTypeDO institutionTypeDO = institutionTypeUpdateDTO.to(InstitutionTypeDO.class);
        // 查询同名制度分类
        List<InstitutionTypeDO> institutionTypeDOList = selectByName(institutionTypeDO
                .getInstitutionTypeName(), tokenUser.getSiteId());
        // 跳过当前修改分类
        institutionTypeDOList = institutionTypeDOList.parallelStream().filter(institutionType
                -> !institutionType.getId().equals(institutionTypeUpdateDTO.getId())).collect(Collectors.toList());
        ParamException.isTrue(CollectionUtils.isEmpty(institutionTypeDOList), "该名称已存在，无法修改");
        // 无法更改上级分类
        institutionTypeDO.setParentId(null);
        // 无法更改分类等级
        institutionTypeDO.setLevel(null);
        //根据主键更新，只更新非null值
        return updateByIdSelective(institutionTypeDO, tokenUser.getSiteId(), tokenUser.getUserId());
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public int deleteByIds(TokenUser tokenUser, String... institutionTypeIds) {
        // 放入下级分类 删除的时候一起删除
        List<String> institutionTypeIdList = new ArrayList<>(Arrays.asList(institutionTypeIds));
        List<InstitutionTypeDO> institutionTypeDOList = selectDOByParentIds(institutionTypeIdList, tokenUser.getSiteId());
        if (!CollectionUtils.isEmpty(institutionTypeDOList)) {
            institutionTypeIdList.addAll(institutionTypeDOList.parallelStream().map(BaseDO::getId).collect(Collectors.toList()));
        }
        List<InstitutionDO> institutionDOList = institutionService
                .selectByTypeIds(institutionTypeIdList, tokenUser.getSiteId());
        ParamException.isTrue(CollectionUtils.isEmpty(institutionDOList), "选中的分类下有制度存在，无法删除");
        return logicalDeleteByIds(tokenUser.getSiteId(), tokenUser.getUserId(), (Object[]) institutionTypeIds);
    }


    @Override
    public InstitutionTypeVO selectById(String institutionTypeId, String siteId) {
        InstitutionTypeDO institutionTypeDO = selectDOById(institutionTypeId, siteId);
        if (institutionTypeDO == null) {
            return null;
        }
        return institutionTypeDO.to(InstitutionTypeVO.class);
    }

    @Override
    public List<InstitutionTypeListVO> select(InstitutionTypeQuery institutionTypeQuery, String siteId) {
        List<InstitutionTypeDO> institutionTypeDOList = selectDO(institutionTypeQuery, siteId);
        if (CollectionUtils.isEmpty(institutionTypeDOList)) {
            return institutionTypeDOList == null ? null : new ArrayList<>();
        }
        return institutionTypeDOList.stream()
                .map(institutionTypeDO -> institutionTypeDO.to(InstitutionTypeListVO.class))
                .collect(Collectors.toList());
    }

    @Override
    public int selectCount(InstitutionTypeQuery institutionTypeQuery, String siteId) {
        Example example = buildExample(institutionTypeQuery, siteId);
        return institutionTypeDAO.selectCountByExample(example);
    }

    @Override
    public Page<InstitutionTypeListVO> selectPage(InstitutionTypeQuery institutionTypeQuery, String siteId) {
        Example example = buildExample(institutionTypeQuery, siteId);
        Page<InstitutionTypeDO> page = institutionTypeDAO.selectPageByExample(example,
                institutionTypeQuery.getPageNo(),
                institutionTypeQuery.getPageSize());

        return page.to(InstitutionTypeListVO.class);
    }

    @Override
    public InstitutionTypeDO selectDOById(String institutionTypeId, String siteId) {
        return listById(institutionTypeId, siteId);
    }

    @Override
    public List<InstitutionTypeDO> selectDOByIds(List<String> institutionTypeIds, String siteId) {
        if (CollectionUtils.isEmpty(institutionTypeIds)) {
            return new ArrayList<>();
        }
        Example example = new Example(InstitutionTypeDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("siteId", siteId)
                .andIn("id", institutionTypeIds);
        return institutionTypeDAO.selectByExample(example);
    }

    @Override
    public List<InstitutionTypeDO> selectDOByParentIds(List<String> parentIds, String siteId) {
        if (CollectionUtils.isEmpty(parentIds)) {
            return new ArrayList<>();
        }
        Example example = new Example(InstitutionTypeDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("siteId", siteId)
                .andIn("parentId", parentIds);
        return institutionTypeDAO.selectByExample(example);
    }

    @Override
    public List<InstitutionTypeDO> selectDO(InstitutionTypeQuery institutionTypeQuery, String siteId) {
        Example example = buildExample(institutionTypeQuery, siteId);
        return institutionTypeDAO.selectByExample(example);
    }

    @Override
    public List<InstitutionTypeListVO> selectTreeByCompany(String companyId, String siteId) {
        // 一级分类
        Example example = new Example(InstitutionTypeDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("parentId", "0")
                .andEqualTo("siteId", siteId);
        List<InstitutionTypeDO> institutionTypeDOList = institutionTypeDAO.selectByExample(example);
        // 二级分类
        List<InstitutionTypeDO> institutionTypeList = selectDOByParentIds(institutionTypeDOList
                .parallelStream().map(BaseDO::getId).collect(Collectors.toList()), siteId);
        // 制度分类下的制度
        List<InstitutionDO> institutionDOList = institutionService.selectByTypeIdsAndCompanyId(
                institutionTypeList.parallelStream().map(BaseDO::getId).collect(Collectors.toList())
                , companyId, siteId);
        // 按制度分类分组
        Map<String, List<InstitutionDO>> institutionTypeListMap = institutionDOList.parallelStream()
                .collect(Collectors.groupingBy(InstitutionDO::getInstitutionTypeId));
        // 父类Id-List
        Map<String, List<InstitutionTypeDO>> parentIdListMap = institutionTypeList.parallelStream()
                .collect(Collectors.groupingBy(InstitutionTypeDO::getParentId));
        return institutionTypeDOList.parallelStream().map(institutionTypeDO -> {
            InstitutionTypeListVO institutionTypeListVO = institutionTypeDO.to(InstitutionTypeListVO.class);
            // 一级分类下的二级分类
            List<InstitutionTypeDO> list = parentIdListMap.get(institutionTypeListVO.getId());
            if (!CollectionUtils.isEmpty(list)) {
                institutionTypeListVO.setHadInstitution(Boolean.TRUE);
                List<InstitutionTypeListVO> institutionTypeListVOList = list.parallelStream().map(typeDO -> {
                    InstitutionTypeListVO listVO = typeDO.to(InstitutionTypeListVO.class);
                    List<InstitutionDO> institutionList = institutionTypeListMap.get(listVO.getId());
                    if (!CollectionUtils.isEmpty(institutionList)) {
                        listVO.setInstitutionVOList(institutionList.parallelStream().map(institutionDO -> {
                                    InstitutionVO institutionVO = institutionDO.to(InstitutionVO.class);
                                    // 制度内容为空 返回空字符串
                                    if (StringUtils.isEmpty(institutionVO.getInstitutionContent())) {
                                        institutionVO.setInstitutionContent("");
                                    }
                                    if (StringUtils.isEmpty(institutionVO.getPlainText())) {
                                        institutionVO.setPlainText("");
                                    }
                                    return institutionVO;
                                }).sorted(Comparator.comparing(InstitutionVO::getIsOpen).reversed())
                                .sorted(Comparator.comparing(InstitutionVO::getGmtCreate).reversed())
                                .collect(Collectors.toList()));
                    }
                    // 是否具备制度
                    listVO.setHadInstitution(!CollectionUtils.isEmpty(institutionList));
                    return listVO;
                }).sorted(Comparator.comparing(InstitutionTypeListVO::getSort)).collect(Collectors.toList());
                institutionTypeListVO.setChildList(institutionTypeListVOList);
                // 一级分类不需要判断是否具备制度
                institutionTypeListVO.setHadInstitution(null);
            }
            return institutionTypeListVO;
        }).sorted(Comparator.comparing(InstitutionTypeListVO::getSort)).collect(Collectors.toList());
    }

    @Override
    public List<InstitutionTypeListVO> selectFirstBySite(String siteId) {
        Example example = new Example(InstitutionTypeDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("siteId", siteId)
                .andEqualTo("level", 1);
        List<InstitutionTypeDO> institutionTypeDOList = institutionTypeDAO.selectByExample(example);
        return institutionTypeDOList.parallelStream().map(institutionTypeDO
                -> institutionTypeDO.to(InstitutionTypeListVO.class)).collect(Collectors.toList());
    }

    @Override
    public List<InstitutionTypeDO> selectByName(String name, String siteId) {
        Example example = new Example(InstitutionTypeDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("siteId", siteId)
                .andEqualTo("institutionTypeName", name);
        return institutionTypeDAO.selectByExample(example);
    }

    @Override
    public InstitutionStatisticalVO selectInstitutionByCompanyId(String companyId, String siteId) {
        ParamException.notNull(companyId, "用工单位Id不能为空");
        InstitutionStatisticalVO institutionStatisticalVO = new InstitutionStatisticalVO();
        // 制度分类
        List<InstitutionTypeListVO> institutionTypeListVOList = selectTreeByCompany(companyId, siteId);
        // 制度分类为空直接返回空对象
        if (CollectionUtils.isEmpty(institutionTypeListVOList)) {
            institutionStatisticalVO.setAllCount(0);
            institutionStatisticalVO.setHadCount(0);
            institutionStatisticalVO.setNotCount(0);
            institutionStatisticalVO.setInstitutionTypeListVOList(new ArrayList<>());
            institutionStatisticalVO.setHadListVOList(new ArrayList<>());
            institutionStatisticalVO.setNotListVOList(new ArrayList<>());
            return institutionStatisticalVO;
        }
        // 应有制度
        int allCount = 0;
        // 已具备制度
        int hadCount = 0;
        // 未具备制度
        int notCount = 0;
        // 制度分类及分类下制度 过滤只有一级的分类
        List<InstitutionTypeListVO> institutionTypeList = new ArrayList<>();
        // 已具备的制度分类及分类下的制度 过滤只有一级的分类
        List<InstitutionTypeListVO> hadListVOList = new ArrayList<>();
        // 未具备的制度分类及分类下的制度 过滤只有一级的分类
        List<InstitutionTypeListVO> notListVOList = new ArrayList<>();
        for (InstitutionTypeListVO institutionTypeListVO : institutionTypeListVOList) {
            List<? extends BaseTreeVO> childList = institutionTypeListVO.getChildList();
            // 没有二级分类的一级分类跳过
            if (CollectionUtils.isEmpty(childList)) {
                continue;
            }
            institutionTypeList.add(institutionTypeListVO);
            List<InstitutionTypeListVO> childVOList = childList.parallelStream().map(baseTreeVO
                    -> baseTreeVO.to(InstitutionTypeListVO.class)).collect(Collectors.toList());
            allCount += childVOList.size();
            // 有制度的二级分类
            List<InstitutionTypeListVO> hadVOList = childVOList.parallelStream().filter(typeListVO
                    -> !CollectionUtils.isEmpty(typeListVO.getInstitutionVOList())).collect(Collectors.toList());
            if (!CollectionUtils.isEmpty(hadVOList)) {
                InstitutionTypeListVO hadVO = institutionTypeListVO.to(InstitutionTypeListVO.class);
                hadVO.setChildList(hadVOList);
                hadVO.setHasChild(Boolean.TRUE);
                hadCount += hadVOList.size();
                hadListVOList.add(hadVO);
            }
            // 没有制度的二级分类
            List<InstitutionTypeListVO> notVOList = childVOList.parallelStream().filter(typeListVO
                    -> CollectionUtils.isEmpty(typeListVO.getInstitutionVOList())).collect(Collectors.toList());
            if (!CollectionUtils.isEmpty(notVOList)) {
                InstitutionTypeListVO notVO = institutionTypeListVO.to(InstitutionTypeListVO.class);
                notVO.setChildList(notVOList);
                notVO.setHasChild(Boolean.TRUE);
                notCount += notVOList.size();
                notListVOList.add(notVO);
            }
        }

        // 应有制度
        institutionStatisticalVO.setAllCount(allCount);
        // 已具备制度
        institutionStatisticalVO.setHadCount(hadCount);
        // 未具备制度
        institutionStatisticalVO.setNotCount(notCount);
        // 制度分类及分类下制度 过滤只有一级的分类
        institutionStatisticalVO.setInstitutionTypeListVOList(institutionTypeList);
        institutionStatisticalVO.setHadListVOList(hadListVOList);
        institutionStatisticalVO.setNotListVOList(notListVOList);
        return institutionStatisticalVO;
    }


    /**
     * 根据查询参数，构建example
     *
     * @param institutionTypeQuery 查询参数
     * @param siteId               所属站点id
     * @return example
     */
    private Example buildExample(InstitutionTypeQuery institutionTypeQuery, String siteId) {
        Example example = new Example(InstitutionTypeDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("siteId", siteId);
        if (institutionTypeQuery.getParentId() != null) {
            example.and().andEqualTo("parentId", institutionTypeQuery.getParentId());
        }
        if (institutionTypeQuery.getLevel() != null) {
            example.and().andEqualTo("level", institutionTypeQuery.getLevel());
        }
        // 排序
        ExampleKit.setExampleOrder(example, institutionTypeQuery.getOrders());
        return example;
    }
}




